﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using OilRigSumoWrestlers.Artificial_intelligence;
using RaptorEngine;
using RaptorEngine.Components;
using OilRigSumoWrestlers.Levels;

namespace OilRigSumoWrestlers.Controllables.Controllers
{
    /// <summary>
    /// Controllable for AI players
    /// </summary>
    class AIControllable: PlayerControllable
    {
        /// <summary>
        /// The current behavior of the AI
        /// </summary>
        public Behavior CurrentBehavior { get; set; }

        private Entity _enemy;
        private ALevel _level;
        private Movable _enemyMovable;
        private Movable _agentMovable;

        public AIControllable(Entity entity, Entity enemy, ALevel level)
            : base(entity)
        {
            _enemy = enemy;
            _level = level;

            if (_enemy.HasComponent(ComponentType.Movable))
                _enemyMovable = (Movable)_enemy.GetComponent(ComponentType.Movable);
            if (Entity.HasComponent(ComponentType.Movable))
                _agentMovable = (Movable)Entity.GetComponent(ComponentType.Movable);

            CurrentBehavior = new EvadeBehavior(Entity, _enemy, this, _level);
        }

        /// <summary>
        /// Sets which enemy the AI will attack or evade
        /// </summary>
        /// <param name="enemy">The enemy entity</param>
        public void SetEnemy(Entity enemy)
        {
            _enemy = enemy;
            if (_enemy.HasComponent(ComponentType.Movable))
                _enemyMovable = (Movable)_enemy.GetComponent(ComponentType.Movable); 
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
            ChooseBehavior(gameTime);
            CurrentBehavior.Update(gameTime);
        }

        private void ChooseBehavior(GameTime gameTime)
        {
            float distanceToEnemy = Vector3.Distance(Entity.Position, _enemy.Position);
            bool approachingEnemy = distanceToEnemy > Vector3.Distance(Entity.Position + _agentMovable.Velocity, _enemy.Position + _enemyMovable.Velocity);


            if (AIHelper.IsPathObstructed(_level.GetIndexAtPosition(Entity.Position), _level.GetIndexAtPosition(_enemy.Position), _level)
                || (_enemyMovable.Velocity.Length() > _agentMovable.Velocity.Length() * GameConstant.AI_AVOID_VELOCITY_MULTIPLIER && approachingEnemy))
            {
                if (CurrentBehavior.GetType() != typeof(EvadeBehavior))
                    CurrentBehavior = new EvadeBehavior(Entity, _enemy, this, _level);
            }
            else
            {
                if (CurrentBehavior.GetType() != typeof(AttackBehavior))
                    CurrentBehavior = new AttackBehavior(Entity, _enemy, this, _level);
            }

            CurrentBehavior.DistanceToEnemy = distanceToEnemy;
            CurrentBehavior.ApproachingEnemy = approachingEnemy;

            GameEngine.Instance.Debug.SetData("Approaching Enemy", approachingEnemy.ToString());
            GameEngine.Instance.Debug.SetData("Distance to Enemy", distanceToEnemy.ToString());
            GameEngine.Instance.Debug.SetData("Behavior", CurrentBehavior.ToString());
            GameEngine.Instance.Debug.SetData("Position", Entity.Position.ToString());
            GameEngine.Instance.Debug.SetData("Rotation", Entity.Rotation.ToString());
        }
    }
}
